const mapshaper = require('mapshaper')
const unzipper = require('unzipper')
const fs = require('fs')

const SUPPORT_TYPE = ['shp', 'shx', 'dbf', 'prj']
/**
 * 将shp系列文件转换为geojson格式json文件
 * @param {Map} inputFiles 
 *    含shp系列文件Buffer的Map对象
 *    含zip文件Buffer的Map对象
 * @param {String} outputName 输出文件名称,不含后缀,可选,默认'export'
 */
function shp2geojson(inputFiles, outputName) {
  return new Promise(async (resolve, reject) => {
    let {shpFile, shxFile, prjFile, dbfFile, zipFile} = inputFiles
    // 参数检查
    // shp系列和zip 有且只有一个
    if (shpFile && zipFile || (!shpFile && !zipFile)) {
      //跳出，阻止后面代码执行
      return reject(new Error('参数错误,请传入shp系列文件或zip文件！'))
    } 
    outputName = outputName ? `${outputName}.json` : 'export.json'
    // 组装input对象
    let input = {}
    // 如果是zip,先解压再转换
    if (zipFile) {
      input = await unzip(zipFile)
    } else {
      input['input.shp'] = shpFile
      if (shxFile) input['input.shx'] = shxFile
      if (dbfFile) input['input.dbf'] = dbfFile
      if (prjFile) input['input.prj'] = prjFile
    }
    // 开始转换
    mapshaper.applyCommands(
      `-i input.shp -o ${outputName}`,
      input,
      (err, result) => {
        if (err) {
          reject(err)
        } else {
          resolve(result)
        }
      }
    )
  })
}
/**
 * 将geojson格式的json文件转换为shp系列文件
 * @param {Buffer} inputFile 要转换的json文件
 * @param {String} outputName 输出文件名称,不含后缀,可选,默认'export'
 * @returns {Promise} 
 *    reject error Object
 *    resolve [Object] 转换结果对象，属性为文件名，属性值为文件[Buffer]
 */
function geojson2shp(inputFile, outputName) {
  const input = {}
  outputName = outputName ? `${outputName}.json` : 'export.json'
  input[outputName] = inputFile
  return new Promise((resolve, reject) => {
    mapshaper.applyCommands(
      `-i ${outputName} -o format=shapefile`,
      input,
      (err, result) => {
        if (err) {
          reject(err)
        } else {
          resolve(result)
        }
      }
    )
  })
}
/**
 * 将zip文件转换为标准输入文件形式
 * @param {Buffer} buffer zip文件的Buffer形式
 */
async function unzip(buffer) {
  // 从zip的Buffer中拿到zip中包含的文件
  const directory = await unzipper.Open.buffer(buffer)
  let result = {}
  // 将shp相关文件装入result对象
  for (let i = 0, length = directory.files.length; i < length; i++) {
    const file = directory.files[i]
    //如 testdata.shp.xml 
    const path = file.path
    const ext = path.substring(path.lastIndexOf('.') + 1)
    if (SUPPORT_TYPE.includes(ext)) {
      const name = `input.${ext}`
      result[name] = await file.buffer()
    }
  }
  return result
}
module.exports = {
  shp2geojson,
  geojson2shp,
}